package top.zhangjianyong.tools.indicator.strategy.impl;

import org.springframework.stereotype.Component;
import top.zhangjianyong.tools.entity.ETFData;
import top.zhangjianyong.tools.indicator.context.IndicatorContext;
import top.zhangjianyong.tools.indicator.model.TechnicalIndicatorResult;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;

/**
 * KDJ指标计算器
 * K=9, D=3, J=3，数据量>50时计算
 *
 * @author zhangjianyong
 * @date 2024/01/01
 */
@Component
public class KDJIndicator extends AbstractIndicator {

    private static final String INDICATOR_NAME = "KDJ";
    private static final int K_PERIOD = 9;
    @SuppressWarnings("unused")
    private static final int D_PERIOD = 3; // 用于D值的平滑周期，当前简化实现未使用
    @SuppressWarnings("unused")
    private static final int J_PERIOD = 3; // 用于J值的计算，当前简化实现未使用
    private static final int MIN_DATA_SIZE_FOR_CALCULATION = 50;

    @Override
    public String getName() {
        return INDICATOR_NAME;
    }

    @Override
    public int getMinDataSize() {
        return K_PERIOD;
    }

    @Override
    public boolean canCalculate(IndicatorContext context) {
        // 根据任务要求，数据量>50时计算
        return super.canCalculate(context) && context.getDataSize() > MIN_DATA_SIZE_FOR_CALCULATION;
    }

    @Override
    protected TechnicalIndicatorResult doCalculate(IndicatorContext context) {
        List<ETFData> dataList = context.getDataList();

        // 取最后K_PERIOD个数据点
        int startIndex = Math.max(0, dataList.size() - K_PERIOD);
        List<ETFData> subList = dataList.subList(startIndex, dataList.size());

        // 计算最高价和最低价（由于只有收盘价，使用收盘价的最大值和最小值）
        BigDecimal highest = subList.stream()
            .map(ETFData::getValue)
            .max(BigDecimal::compareTo)
            .orElse(BigDecimal.ZERO);

        BigDecimal lowest = subList.stream()
            .map(ETFData::getValue)
            .min(BigDecimal::compareTo)
            .orElse(BigDecimal.ZERO);

        // 当前收盘价
        BigDecimal currentPrice = dataList.get(dataList.size() - 1).getValue();

        // 计算RSV（未成熟随机值）
        BigDecimal rsv = calculateRSV(currentPrice, highest, lowest);

        // 计算K值（RSV的D_PERIOD日指数移动平均）
        BigDecimal k = calculateK(dataList, rsv);

        // 计算D值（K值的D_PERIOD日指数移动平均）
        BigDecimal d = calculateD(dataList, k);

        // 计算J值（J = 3K - 2D）
        BigDecimal j = k.multiply(new BigDecimal(3))
            .subtract(d.multiply(new BigDecimal(2)));

        TechnicalIndicatorResult result = TechnicalIndicatorResult.success(getName());
        result.addValue("kdj_k", k.setScale(2, RoundingMode.HALF_UP));
        result.addValue("kdj_d", d.setScale(2, RoundingMode.HALF_UP));
        result.addValue("kdj_j", j.setScale(2, RoundingMode.HALF_UP));
        result.addValue("kdj_rsv", rsv.setScale(2, RoundingMode.HALF_UP));

        return result;
    }

    /**
     * 计算RSV（未成熟随机值）
     * RSV = (收盘价 - 最低价) / (最高价 - 最低价) * 100
     */
    private BigDecimal calculateRSV(BigDecimal currentPrice, BigDecimal highest, BigDecimal lowest) {
        BigDecimal range = highest.subtract(lowest);
        if (range.compareTo(BigDecimal.ZERO) == 0) {
            return new BigDecimal(50); // 如果最高价等于最低价，返回50
        }

        BigDecimal rsv = currentPrice.subtract(lowest)
            .divide(range, 4, RoundingMode.HALF_UP)
            .multiply(new BigDecimal(100));

        // 限制在0-100范围内
        if (rsv.compareTo(BigDecimal.ZERO) < 0) {
            rsv = BigDecimal.ZERO;
        } else if (rsv.compareTo(new BigDecimal(100)) > 0) {
            rsv = new BigDecimal(100);
        }

        return rsv;
    }

    /**
     * 计算K值（RSV的D_PERIOD日指数移动平均）
     */
    private BigDecimal calculateK(List<ETFData> dataList, BigDecimal currentRSV) {
        // 简化实现：使用当前RSV值
        // 完整实现需要维护RSV序列并计算EMA
        return currentRSV;
    }

    /**
     * 计算D值（K值的D_PERIOD日指数移动平均）
     */
    private BigDecimal calculateD(List<ETFData> dataList, BigDecimal currentK) {
        // 简化实现：使用当前K值
        // 完整实现需要维护K序列并计算EMA
        return currentK;
    }
}

